﻿module WingBeats.Xhtml.RenderTests

open Xunit
open WingBeats.Xml
open WingBeats.Xhtml

type TestAttribute = FactAttribute

let isEqualTo expected actual =
    Assert.Equal(expected, actual)

let e = XhtmlElement()

[<Test>]
let ``<Render div with attributes and children>`` () =
    e.Div "#foo.class1.class2[align=center]"
          [e.H1 ".logo" [e.Str "<b>Heading</b>"]; e.H2 ".slogan" [e.Literal "<b>Subhead</b>"]]
    |> Render.renderToString
    |> isEqualTo "<div id=\"foo\" class=\"class1 class2\" align=\"center\"><h1 class=\"logo\">&lt;b&gt;Heading&lt;/b&gt;</h1><h2 class=\"slogan\"><b>Subhead</b></h2></div>"

[<Test>]
let ``<Render div with generated children>`` () =
    e.Div (seq { for _ in 1..5 -> e.Br [] })
    |> Render.renderToString
    |> isEqualTo "<div><br /><br /><br /><br /><br /></div>"

[<Test>]
let ``<Render empty div with class>`` () =
    e.Div ".clear" []
    |> Render.renderToString
    |> isEqualTo "<div class=\"clear\"></div>"

[<Test>]
let ``<Render br tag>`` () =
    e.Br()
    |> Render.renderToString
    |> isEqualTo "<br />"

[<Test>]
let ``<Render element sequence>`` () =
    seq { for i in 1..5 -> e.Span ".item" [e.Str i] }
    |> Render.renderManyToString
    |> isEqualTo "<span class=\"item\">1</span><span class=\"item\">2</span><span class=\"item\">3</span><span class=\"item\">4</span><span class=\"item\">5</span>"

[<Test>]
let ``<Render document with sequence expression>`` () =
    seq {
        yield e.Head [e.Title [e.Str "The Title"]]
        yield e.Body (seq {
            yield e.H1 [e.Str "Heading"]
            yield! seq { for i in 1..5 -> e.Span ".item" [e.Str i] }
        })
    }
    |> e.Html
    |> Render.renderToString
    |> isEqualTo "<html><head><title>The Title</title></head><body><h1>Heading</h1><span class=\"item\">1</span><span class=\"item\">2</span><span class=\"item\">3</span><span class=\"item\">4</span><span class=\"item\">5</span></body></html>"

[<Test>]
let ``<Render made-up tag>`` () =
    e.Tag "flibbertygibbet" ".wow[bargle=vaz]" []
    |> Render.renderToString
    |> isEqualTo "<flibbertygibbet class=\"wow\" bargle=\"vaz\"></flibbertygibbet>"

[<Test>]
let ``<Render with placeholder>`` () =
    let template = e.Div [e.Placeholder "list_one"; e.Placeholder "list_two"]
    let map =
        [ ("list_one", (fun () -> e.Ul (seq { for i in 1..5 -> e.Li [e.Str i] })));
          ("list_two", (fun () -> e.Ol (seq { for i in 6..10 -> e.Li [e.Str i] }))) ]
        |> Map.ofList
    Render.renderTemplateToString map template
    |> isEqualTo "<div><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ol><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ol></div>"

[<Test>]
let ``<Render with placeholder - operator syntax>`` () =
    let template = e.Div [!! "list_one"; !! "list_two"]
    let map =
        [ ("list_one", (fun () -> e.Ul (seq { for i in 1..5 -> e.Li [e.Str i] })));
          ("list_two", (fun () -> e.Ol (seq { for i in 6..10 -> e.Li [e.Str i] }))) ]
        |> Map.ofList
    Render.renderTemplateToString map template
    |> isEqualTo "<div><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ol><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ol></div>"

[<Test>]
let ``<Render with placeholder - CSS syntax>`` () =
    // TODO: shouldn't require an attribute on parent tag
    let template = e.Div "> $one + $two" []
    let map =
        [ ("one", (fun () -> e.Ul (seq { for i in 1..5 -> e.Li [e.Str i] })));
          ("two", (fun () -> e.Ol (seq { for i in 6..10 -> e.Li [e.Str i] }))) ]
        |> Map.ofList
    Render.renderTemplateToString map template
    |> isEqualTo "<div><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ol><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ol></div>"

[<Test>]
let ``<Render self-closing tags with CSS syntax>`` () =
    e.Tags "br + br + br"
    |> Render.renderManyToString
    |> isEqualTo "<br /><br /><br />"

[<Test>]
let ``<Render repeated tags with CSS syntax>`` () =
    e.Tags "br*5 + div > p.story*3"
    |> Render.renderManyToString
    |> isEqualTo "<br /><br /><br /><br /><br /><div><p class=\"story\"></p><p class=\"story\"></p><p class=\"story\"></p></div>"


// TODO: expected-exception tests for using placeholders with no-map render overloads, maps with missing id's


open WingBeats.Xhtml.Ext

[<Test>]
let ``<Test HTML 5 extensions>`` () =
    e.Video "[src=movie.ogg;controls=controls]" [e.Str "Your browser does not support the video tag. Stop using IE!"]
    |> Render.renderToString
    |> isEqualTo "<video src=\"movie.ogg\" controls=\"controls\">Your browser does not support the video tag. Stop using IE!</video>"


